package cn.wolfcode.shop.cloud.filter;

import cn.wolfcode.shop.cloud.common.CodeMsg;
import cn.wolfcode.shop.cloud.common.JSONUtil;
import cn.wolfcode.shop.cloud.common.Result;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.ERROR_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_ERROR_FILTER_ORDER;

/**
 * Created by wolfcode-lanxw
 */
@Slf4j
@Component
public class WolfcodeSendErrorFilter extends ZuulFilter {

    protected static final String SEND_ERROR_FILTER_RAN = "sendErrorFilter.ran";

    @Override
    public String filterType() {
        return ERROR_TYPE;
    }

    @Override
    public int filterOrder() {
        return SEND_ERROR_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        // only forward to errorPath if it hasn't been forwarded to already
        return ctx.getThrowable() != null
                && !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false);
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        Throwable exception = ctx.getThrowable();
        HttpServletResponse resp = ctx.getResponse();

        log.warn("Error during filtering", exception);

        try {
            CodeMsg errorMsg = CodeMsg.DEFAULT_ERROR;
            // 从上下文中获取RateLimit限流标识
            String rateLimitExceeded = (String) ctx.get("rateLimitExceeded");
            // 如果限流标识为true,则表示当前请求触发限流规则
            if (!StringUtils.isEmpty(rateLimitExceeded) && rateLimitExceeded.equalsIgnoreCase(Boolean.TRUE.toString())) {
                // 请求被限制了
                errorMsg = CodeMsg.TOO_MANY_REQUESTS;
            }

            // 将错误消息响应给前端
            resp.setContentType("application/json;charset=utf-8");
            resp.getWriter().write(JSONUtil.toJSONString(Result.error(errorMsg)));
        } catch (Exception e) {
            ReflectionUtils.rethrowRuntimeException(e);
        }
        return null;
    }
}
